package cn.likun.kit.database.dialect;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.likun.kit.ReadResource;
import cn.likun.kit.database.DB_TYPE;
import cn.likun.kit.database.bean.Pagination;
import cn.likun.kit.string.StringCommons;
import cn.likun.kit.validate.ValidateCommons;

/**
 *<p>SQL 语句方言处理工具类</p>
 *配置方式:<br>
 *每种数据库对应一个properties文件<br> 
 *oracle > oracle.properties<br>
 *db2 > db2.properties<br>
 *mysql > mysql.properties<br>
 *sqlserver > sqlserver.properties<br>
 *properties 文件中以方法名作key,可以格式化资源值<br>
 */
public class DialectCommons {
	
	private static Map<DB_TYPE,DialectCommons> caches = new HashMap<DB_TYPE,DialectCommons>();
	
	private String resourceName;
	/**
	 * <p>获取DialectCommons 实例</p>
	 * @param dbType 数据库类型
	 */
	public static DialectCommons getInstance(DB_TYPE dbType) {
		DialectCommons dialect = caches.get(dbType);
		if (ValidateCommons.isEmpty(dialect)) {
			dialect = new DialectCommons(dbType);
			caches.put(dbType, dialect);
		}
		return dialect;
	}
	/**
	 * 构造函数
	 * @param dbType
	 */
	protected DialectCommons(DB_TYPE dbType){
		StringBuffer strb = new StringBuffer("com.such.kit.database.dialect.configs.");
		if (DB_TYPE.ORACLE.equals(dbType)) {
			strb.append("oracle");
		} else if (DB_TYPE.MYSQL.equals(dbType)) {
			strb.append("mysql");
		} else if (DB_TYPE.SQLSERVER.equals(dbType)) {
			strb.append("sqlserver");
		} else if (DB_TYPE.DB2.equals(dbType)) {
			strb.append("db2");
		}
		strb.append(".properties");
		this.resourceName = strb.toString();
	}
	/**
	 * 构建伪表查询
	 * 参数对应 sqlFragment --> {0} <br>
	 * @param sqlFragment sql片段
	 * @return 
	 */
	public String buildDummyTableSql(String sqlFragment) {
		Object[] args = new Object[1];
		args[0] = sqlFragment;
		String dummyTableSql = ReadResource.getValue(resourceName, "buildDummyTableSql");
		dummyTableSql = ReadResource.formatValue(dummyTableSql, args);
		return dummyTableSql;
	}
	
	/**
	 * <p>构建获取下一个序列值语句(不包括伪表查询)</p>
	 * <p>
	 * 参数对应:  <br>
	 * 	sequenceName --> {0}<br>
	 *  alias --> {1}
	 *  </p>
	 * @param sequenceName 序列名称
	 * @param alias  值别名，可为空，默认值为 NEXT_VALUE
	 * @return
	 */
	public String buildSequenceNextValueSql(String sequenceName, String alias) {
		if (ValidateCommons.isEmpty(alias)) {
			alias = "NEXT_VALUE";
		}
		Object[] args = new Object[2];
		args[0] = sequenceName;
		args[1] = alias;
		String sequenceNextValueSql = ReadResource.getValue(resourceName, "buildSequenceNextValeSql");
		sequenceNextValueSql = ReadResource.formatValue(sequenceNextValueSql, args);
		return sequenceNextValueSql;
	}
	/**
	 * 构建call语句,用于调用存储过程 函数等 <br>
	 * <p>
	 * 
	 * </p>
	 * @param callName call 的对象名
	 * @param params 参数列表，需要进行参数绑定可以传入 ?，直接传入值需要自行根据类型判断是否需要使用 'val'
	 * @return
	 */
	public String buildCallSql(String callName, List<String> params) {
		String paramsString = "";
		if (ValidateCommons.isNotEmpty(params)) {
			StringCommons.merger(params.toArray(new String[]{}),"," ,true);
		}
		Object[] args = new Object[2];
		args[0] = callName;
		args[1] = paramsString;
		String callSql = ReadResource.getValue(resourceName, "buildCallSql");
		callSql = ReadResource.formatValue(callSql, args);
		return callSql;
	}
	/**
	 * 构建分页语句
	 * <p>
	 * 占位符:<br>
	 * sql --> {0}<br>
	 * pageIndex --> {1} <br>
	 * pageLimit --> {2} <br>
	 * startRow 下标从1开始 --> {3}<br>
	 * startRowSubscript0 下标从0开始 -->{4}<br>
	 * endRow 下标从1开始 --> {5}<br>
	 * endRowSubscript0 下标从0开始 -->{6}<br>
	 * </p>
	 * @param sql 
	 * @param pageIndex
	 * @param pageLimit
	 * @return
	 */
	public String buildPagingSql(String sql,int pageIndex , int pageLimit ) {
		Pagination<Object> pagination = new Pagination<Object>(pageIndex,pageLimit);
		Object[] args = new Object[7];
		args[0] = sql ;
		args[1] = String.valueOf(pageIndex);
		args[2] = String.valueOf(pageLimit);
		args[3] = String.valueOf(pagination.getStartRow());
		args[4] = String.valueOf(pagination.getStartRowSubscript0());
		args[5] = String.valueOf(pagination.getEndRow());
		args[6] = String.valueOf(pagination.getEndRowSubscript0());
		String pagingSql = ReadResource.getValue(resourceName, "buildPagingSql");
		pagingSql = ReadResource.formatValue(pagingSql, args);
		return pagingSql;
	}
	/**
	 * 构建计数语句
	 * @param sql
	 * @return
	 */
	public String buildCountSql(String sql){
		Object[] args = new Object[1];
		args[0] = sql;
		String countSql = ReadResource.getValue(resourceName, "buildCountSql");
		countSql = ReadResource.formatValue(countSql, args);
		return countSql;
	}
	
}

